﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
using Acme.BookStore2.Permissions;
using Acme.BookStore2.Users;
using Microsoft.AspNetCore.Authorization;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Services;
using Volo.Abp.Identity;
using Volo.Abp.ObjectExtending;
using Volo.Abp.Users;

namespace Acme.BookStore2
{
    [Authorize(BookStore2Permissions.VehicleDriveRecord.Default)]
    public class VehicleDriveRecordAppService : ApplicationService, IVehicleDriveRecordAppService
    {
        private readonly IVehicleDriveRecordRepository _vehicleDriveRecordRepository;
        private readonly IVehicleRepository _vehicleRepository;
        private readonly IIdentityUserRepository _userRepository;
        private readonly VehicleDriveRecordManager _vehicleDriveRecordManager;

        public VehicleDriveRecordAppService(
            IVehicleDriveRecordRepository vehicleDriveRecordRepository, 
            VehicleDriveRecordManager vehicleDriveRecordManager, 
            IVehicleRepository vehicleRepository, 
            IIdentityUserRepository userRepository)
        {
            _vehicleDriveRecordRepository = vehicleDriveRecordRepository;
            _vehicleDriveRecordManager = vehicleDriveRecordManager;
            _vehicleRepository = vehicleRepository;
            _userRepository = userRepository;
        }

        public async Task<VehicleDriveRecordDto> GetAsync(Guid id)
        {
            var vehicleDriveRecord = await _vehicleDriveRecordRepository.GetAsync(id, false);
            var vehicleDriveRecordDto = ObjectMapper.Map<VehicleDriveRecord, VehicleDriveRecordDto>(vehicleDriveRecord); 
            var vehicle = await _vehicleRepository.GetAsync(vehicleDriveRecord.VehicleId);
            var driver = await _userRepository.GetAsync(vehicleDriveRecord.Driver);
            vehicleDriveRecordDto.DriverName = driver.Name + " " + driver.Surname;
            vehicleDriveRecordDto.VehicleNumber = vehicle.Number;
            vehicleDriveRecordDto.VehicleLicensePlateNumber = vehicle.LicensePlateNumber;
            return vehicleDriveRecordDto;
        }

        public async Task<PagedResultDto<VehicleDriveRecordDto>> GetPagedListAsync(GetVehicleDriveRecordsInput input)
        {
            var count = await _vehicleDriveRecordRepository.GetCountAsync(input.VehicleId);
            var list = await _vehicleDriveRecordRepository.GetPagedListAsync(input.SkipCount, input.MaxResultCount,
                input.Sorting, input.VehicleId);
            var pageDto = new PagedResultDto<VehicleDriveRecordDto>(
                count, 
                ObjectMapper.Map<List<VehicleDriveRecord>, List<VehicleDriveRecordDto>>(list));
            foreach (var vehicleDriveRecordDto in pageDto.Items)
            {
                var vehicle = await _vehicleRepository.GetAsync(vehicleDriveRecordDto.VehicleId);
                var driver = await _userRepository.GetAsync(vehicleDriveRecordDto.Driver);
                vehicleDriveRecordDto.DriverName = driver.Name + " " + driver.Surname;
                vehicleDriveRecordDto.VehicleNumber = vehicle.Number;
                vehicleDriveRecordDto.VehicleLicensePlateNumber = vehicle.LicensePlateNumber;
            }

            return pageDto;
        }

        [Authorize(BookStore2Permissions.VehicleDriveRecord.Create)]
        public async Task<VehicleDriveRecordDto> CreateAsync(VehicleDriveRecordCreateDto input)
        {
            var vehicleDriveRecord = new VehicleDriveRecord(
                GuidGenerator.Create(),
                input.VehicleId,
                CurrentTenant.Id);

            UpdateVehicleDriveRecord(vehicleDriveRecord, input);
            input.MapExtraPropertiesTo(vehicleDriveRecord);

            await _vehicleDriveRecordRepository.InsertAsync(vehicleDriveRecord);
            await CurrentUnitOfWork.SaveChangesAsync();

            return ObjectMapper.Map<VehicleDriveRecord, VehicleDriveRecordDto>(vehicleDriveRecord);
        }

        [Authorize(BookStore2Permissions.VehicleDriveRecord.Update)]
        public async Task<VehicleDriveRecordDto> UpdateAsync(Guid id, VehicleDriveRecordUpdateDto input)
        {
            var vehicleDriveRecord = await _vehicleDriveRecordRepository.GetAsync(id);
            vehicleDriveRecord.ConcurrencyStamp = input.ConcurrencyStamp;

            UpdateVehicleDriveRecord(vehicleDriveRecord, input);
            input.MapExtraPropertiesTo(vehicleDriveRecord);

            await _vehicleDriveRecordRepository.UpdateAsync(vehicleDriveRecord);
            await CurrentUnitOfWork.SaveChangesAsync();

            return ObjectMapper.Map<VehicleDriveRecord, VehicleDriveRecordDto>(vehicleDriveRecord);
        }

        [Authorize(BookStore2Permissions.VehicleDriveRecord.Delete)]
        public async Task DeleteAsync(Guid id)
        {
            var vehicleDriveRecord = await _vehicleDriveRecordRepository.FindAsync(id);
            if (vehicleDriveRecord == null)
            {
                return;
            }

            await _vehicleDriveRecordRepository.DeleteAsync(vehicleDriveRecord);
        }

        [Authorize(BookStore2Permissions.VehicleDriveRecord.Export)]
        public async Task ExportAsync(GetVehicleDriveRecordsInput input)
        {
        }

        private void UpdateVehicleDriveRecord(VehicleDriveRecord vehicleDriveRecord, VehicleDriveRecordCreateOrUpdateDtoBase input)
        {
            vehicleDriveRecord.Driver = input.Driver;
            vehicleDriveRecord.DriveTime = input.DriveTime;
            vehicleDriveRecord.Remark = input.Remark;
        }
    }
}